package com.example.chatserver;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.example.chatserver.OnReceive.ReceiveData;



public class TcpNioServer implements Runnable {
	private String message;
	private String ipAddress;
	Selector selector = null;
	ServerSocketChannel server = null;
	InetSocketAddress ip;
	private final List<OnReceive> ls = new ArrayList<OnReceive>();
	private Thread thread;
	private boolean isrunning = false;

	public TcpNioServer(int port) {

		ip = new InetSocketAddress(port);

	}

	public TcpNioServer(String hostname, int port) {
		ip = new InetSocketAddress(hostname, port);
	}

	public void start() {
		if (!isrunning) {
			isrunning = true;
			thread = new Thread(this);
			thread.start();
		}
	}

	public void stop() {
		isrunning = false;
		thread = null;
	}

	public void regsiter(OnReceive receive) {
		ls.add(receive);
	}

	public String receiveMsg() {
		return message;
	}

	public String receiveIP() {
		return ipAddress;
	}

	@Override
	public void run() {
		try {
			selector = Selector.open();
			server = ServerSocketChannel.open();
			server.socket().bind(ip);
			server.configureBlocking(false);
			server.register(selector, SelectionKey.OP_ACCEPT);
			System.out.println("��������ʼ���ܿͻ�������");

			while (isrunning) {
				try {
					selector.select(60000);
					Iterator<SelectionKey> it = selector.selectedKeys().iterator();
					while (it.hasNext()) {
						SelectionKey key = it.next();
						it.remove();
						if (key.isAcceptable()) {
							ServerSocketChannel server2 = (ServerSocketChannel) key.channel();
							SocketChannel channel = server2.accept();
							channel.configureBlocking(false);
							channel.register(selector, SelectionKey.OP_READ);
							System.out.println("�ͻ��ˣ�" + channel.socket().getInetAddress().getHostName() + ":" + channel.socket().getPort() + " ��������");
						}
						if (key.isReadable()) {
							SocketChannel channel = (SocketChannel) key.channel();
							try {
								ByteBuffer buffer = ByteBuffer.allocate(1024);
								buffer.clear();
								byte[] byteStream;
								int count = 0;
								while ((count = channel.read(buffer)) > 0) {
									buffer.flip();
									byteStream=new byte[buffer.limit()];
									buffer.get(byteStream);
								
								}
								if(count == -1){
									disconnect(key,channel);
								}else{
									for (OnReceive receive : ls) {
										try {
											ReceiveData data = new ReceiveData();
											Socket socket = channel.socket();
											data.data = buffer.array();
											data.fromAddress = socket.getRemoteSocketAddress();
											data.port = socket.getPort();
											receive.onReceive(data);
	
										} catch (Exception e) {
											e.printStackTrace();
										}
									}
								}
							} catch (IOException e) {

								System.out.println("�ͻ��ˣ�" + channel.socket().getInetAddress().getHostName() + ":" + channel.socket().getPort() + " �ѶϿ�����");
								channel.close();
								e.printStackTrace();
								continue;
							}

							Thread.sleep(1);
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				selector.close();
				server.close();
			} catch (IOException e) {
			}
			isrunning = false;
		}

	}
	//�Ͽ�����
	private void disconnect(SelectionKey key, SocketChannel sc) {
		try {
			key.cancel();
			sc.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) throws Exception {

		TcpNioServer tns = new TcpNioServer("192.168.0.105", 8899);
		tns.regsiter(new OnReceive() {

			@Override
			public void error(Exception ex) {

			}

			@Override
			public void onReceive(ReceiveData data) {
				String msg = "empty";
				try {
					msg = new String(data.data, ("UTF-16"));
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				String ipAddress = data.fromAddress.toString();
				System.out.println("�ͻ��˵�ip�ǣ�" + ipAddress + " ����������Ϣ�ǣ�" + msg);
			}

		});
		tns.start();
	}
}